home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
t3_1
/
risc_src.lha
/
risc_sources
/
sparc
/
expand.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-08-28
|
3KB
|
125 lines
#include <stdio.h>
/* convert a pathname to an absolute one, if it is absolute already,
it is returned in the buffer unchanged, otherwise leading "./"s
will be removed, and "../"s will be resolved.
In a moment of weakness, I have implemented the cshell ~ filename
convention. ~/foobar will have the ~ replaced by the home directory of
the current user. ~user/foobar will have the ~user replaced by the
home directory of the named user. This should really be in the kernel
(or be replaced by a better kernel mechanism). Doing file name
expansion like this in a user-level program leads to some very
distasteful non-uniformities.
Another fit of dementia has led me to implement the expansion of shell
environment variables. $HOME/mbox is the same as ~/mbox. If the
environment variable a = "foo" and b = "bar" then:
$a => foo
$a$b => foobar
$a.c => foo.c
xxx$a => xxxfoo
${a}! => foo!
James Gosling @ CMU
*/
/* #include <sys/types.h>
#include <sys/stat.h> */
#include <pwd.h>
#include "ctype.h"
expand_path (nm, buf) /* input name in nm, absolute pathname
output to buf. returns 0 on success
-1 on failure with error msg in buf */
char *nm,
* buf; {
register char *s,
*d;
char lnm[1000];
s = nm;
d = lnm;
while (*d++ = *s)
if (*s++ == '$') {
register char *start = d;
register braces = *s == '{';
register char *value;
while (*d++ = *s)
if (braces ? *s == '}' : !(isalpha(*s) || isdigit(*s)
|| (*s == '_')))
break;
else
s++;
*--d = 0;
value = (char *) getenv (braces ? start + 1 : start);
if (value) {
for (d = start - 1; *d++ = *value++;);
d--;
if (braces && *s)
s++;
}
}
d = buf;
nm = lnm;
if (nm[0] == '~') /* prefix ~ */
if (nm[1] == '/' || nm[1] == 0)/* ~/filename */
if (s = (char *) getenv ("HOME")) {
if (*++nm)
nm++;
}
else
s = "";
else { /* ~user/filename */
register char *nnm;
register struct passwd *pw;
for (s = nm; *s && *s != '/'; s++);
nnm = *s ? s + 1 : s;
*s = 0;
pw = (struct passwd *) getpwnam (nm + 1);
if (pw == 0) {
sprintf (buf,"\"%s\" isn't a registered user.", nm+1);
return -1;
}
else {
nm = nnm;
s = pw -> pw_dir;
}
}
while (*d++ = *s++);
if (buf[0] != '\0') *(d - 1) = '/'; else d--;
s = nm;
while (*d++ = *s++);
*(d - 1) = '/';
*d = '\0';
d = buf;
s = buf;
while (*s)
if ((*d++ = *s++) == '/' && d > buf + 1) {
register char *t = d - 2;
switch (*t) {
case '/': /* found // in the name */
--d;
break;
case '.':
switch (*--t) {
case '/': /* found /./ in the name */
d -= 2;
break;
#if 0
case '.':
if (*--t == '/') {/* found /../ */
while (t > buf && *--t != '/');
d = t + 1;
}
break;
#endif
}
break;
}
}
if (*(d - 1) == '/')
d--;
*d = '\0';
return 0;
}